# -*- coding: utf-8 -*-

import re
import json
import logging

from django.views.generic import TemplateView
from django.utils.encoding import smart_unicode
from django.utils.decorators import method_decorator
from django.views.decorators.http import require_POST, require_GET

from api.preset.handler import get_fixed_bucket
from common.cache import redis_cache

from common.preset.db import preset as preset_db
from common.preset.db import loading as loading_db
from common.preset.db import banner as banner_db
from common.preset.db import shortcut as shortcut_db
from common.preset.db import discovery as discovery_db
from common.preset.db import reward as reward_db
from common.preset.db import pay as pay_db
from common.preset.db import recommend as recommend_db
from common.preset.db import float_icon as float_icon_db
from common.preset.db import lottery as lottery_db
from common.preset.db import tab as tab_db
from common.abtest.db import get_abtest
from common.preset.db import profit_rate as profit_rate_db
from common.utils.decorator import response_wrapper
from common.utils.api import token_required
from common.lottery.cyclical.handler import get_daily_pool_info
from common.utils.tz import (
    utc_to_local_str,
    ts_to_local_date_str
)

_LOGGER = logging.getLogger(__name__)


def clean_chn(chn):
    if chn:
        chn = re.sub(r'[^0-9a-zA-Z_]', ',', chn)
        if not chn.startswith(','):
            chn = ',%s' % chn
        if not chn.endswith(','):
            chn = '%s,' % chn
    return chn


class PresetView(TemplateView):
    def get(self, req):
        query_dct = req.GET.dict()
        items, total_count = preset_db.list_preset(query_dct)
        resp_items = []
        for item in items:
            data = item.as_dict()
            data['created_at'] = utc_to_local_str(data['created_at'])
            data['updated_at'] = utc_to_local_str(data['updated_at'])
            data['content'] = json.loads(item.content or '{}')
            resp_items.append(data)

        return {'list': resp_items, 'page': query_dct.get('$page', 1),
                'size': len(resp_items), 'total_count': total_count}

    def post(self, req):
        param_dct = json.loads(req.body)
        param_dct['chn'] = clean_chn(param_dct.get('chn'))
        preset_db.upsert_preset(base=param_dct.get('base'))
        return {}

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(PresetView, self).dispatch(*args, **kwargs)


class SinglePresetView(TemplateView):
    def get(self, req, preset_id):
        preset = preset_db.get_preset(id=int(preset_id))
        data = preset.as_dict()
        data['created_at'] = utc_to_local_str(data['created_at'])
        data['updated_at'] = utc_to_local_str(data['updated_at'])
        data['content'] = json.loads(preset.content or '{}')
        return data

    def post(self, req, preset_id):
        return self.put(req, preset_id)

    def put(self, req, preset_id):
        query_dct = json.loads(smart_unicode(req.body))
        query_dct['chn'] = clean_chn(query_dct['chn'])
        preset_db.upsert_preset(query_dct, int(preset_id))
        return {}

    def delete(self, req, preset_id):
        preset_db.delete_preset(int(preset_id))
        _LOGGER.info('delete preset: %s, user: %s', preset_id, req.user_id)
        return {}

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(SinglePresetView, self).dispatch(*args, **kwargs)


class LoadingView(TemplateView):
    def get(self, req):
        query_dct = req.GET.dict()
        items, total_count = loading_db.list_loading(query_dct)

        resp_items = []
        for item in items:
            item.image = get_fixed_bucket(item.image)
            item.updated_at = utc_to_local_str(item.updated_at)
            item.created_at = utc_to_local_str(item.created_at)
            item.start_ts = ts_to_local_date_str(item.start_ts)
            item.end_ts = ts_to_local_date_str(item.end_ts)
            data = item.as_dict()
            if item.abtest:
                data['abtest'] = get_abtest(item.abtest).name
            resp_items.append(data)

        return {'list': resp_items, 'page': query_dct.get('$page', 1),
                'size': len(resp_items), 'total_count': total_count}

    def post(self, req):
        param_dct = json.loads(req.body)
        param_dct['image'] = get_fixed_bucket(param_dct['image'],
                                              disable_domain=True)
        loading_db.upsert_loading(param_dct)
        return {}

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(LoadingView, self).dispatch(*args, **kwargs)


class SingleLoadingView(TemplateView):
    def get(self, req, loading_id):
        loading = loading_db.get_loading(id=int(loading_id))
        loading.image = get_fixed_bucket(loading.image)
        loading.updated_at = utc_to_local_str(loading.updated_at)
        loading.created_at = utc_to_local_str(loading.created_at)
        loading.start_ts = ts_to_local_date_str(loading.start_ts)
        loading.end_ts = ts_to_local_date_str(loading.end_ts)
        return loading.as_dict()

    def put(self, req, loading_id):
        query_dct = json.loads(smart_unicode(req.body))
        query_dct['image'] = get_fixed_bucket(query_dct['image'],
                                              disable_domain=True)
        loading_db.upsert_loading(query_dct, int(loading_id))
        return {}

    def delete(self, req, loading_id):
        loading_db.delete_loading(int(loading_id))
        return {}

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(SingleLoadingView, self).dispatch(*args, **kwargs)


class ShortcutView(TemplateView):
    def get(self, req):
        query_dct = req.GET.dict()
        items, total_count = shortcut_db.list_shortcut(query_dct)

        resp_items = []
        for item in items:
            item.image = get_fixed_bucket(item.image)
            data = item.as_dict()
            if item.abtest:
                data['abtest'] = get_abtest(item.abtest).name
            resp_items.append(data)

        return {'list': resp_items, 'page': query_dct.get('$page', 1),
                'size': len(resp_items), 'total_count': total_count}

    def post(self, req):
        param_dct = json.loads(req.body)
        param_dct['image'] = get_fixed_bucket(param_dct['image'],
                                              disable_domain=True)
        shortcut_db.upsert_shortcut(param_dct)
        return {}

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(ShortcutView, self).dispatch(*args, **kwargs)


class SingleShortcutView(TemplateView):
    def get(self, req, shortcut_id):
        shortcut = shortcut_db.get_shortcut(id=int(shortcut_id))
        shortcut.image = get_fixed_bucket(shortcut.image)
        return shortcut.as_dict()

    def put(self, req, shortcut_id):
        query_dct = json.loads(smart_unicode(req.body))
        query_dct['image'] = get_fixed_bucket(query_dct['image'],
                                              disable_domain=True)
        shortcut_db.upsert_shortcut(query_dct, int(shortcut_id))
        return {}

    def delete(self, req, shortcut_id):
        shortcut_db.delete_shortcut(int(shortcut_id))
        return {}

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(SingleShortcutView, self).dispatch(*args, **kwargs)


class BannerView(TemplateView):
    def get(self, req):
        query_dct = req.GET.dict()
        items, total_count = banner_db.list_banner(query_dct)

        resp_items = []
        for item in items:
            item.image = get_fixed_bucket(item.image)
            item.updated_at = utc_to_local_str(item.updated_at)
            item.created_at = utc_to_local_str(item.created_at)
            data = item.as_dict()
            if item.abtest:
                data['abtest'] = get_abtest(item.abtest).name
            resp_items.append(data)

        return {'list': resp_items, 'page': query_dct.get('$page', 1),
                'size': len(resp_items), 'total_count': total_count}

    def post(self, req):
        param_dct = json.loads(req.body)
        param_dct['image'] = get_fixed_bucket(param_dct['image'],
                                              disable_domain=True)
        banner_db.upsert_banner(param_dct)
        return {}

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(BannerView, self).dispatch(*args, **kwargs)


class SingleBannerView(TemplateView):
    def get(self, req, banner_id):
        banner = banner_db.get_banner(id=int(banner_id))
        banner.image = get_fixed_bucket(banner.image)
        banner.updated_at = utc_to_local_str(banner.updated_at)
        banner.created_at = utc_to_local_str(banner.created_at)
        return banner.as_dict()

    def put(self, req, banner_id):
        query_dct = json.loads(smart_unicode(req.body))
        query_dct['image'] = get_fixed_bucket(query_dct['image'],
                                              disable_domain=True)
        banner_db.upsert_banner(query_dct, int(banner_id))
        return {}

    def delete(self, req, banner_id):
        banner_db.delete_banner(int(banner_id))
        return {}

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(SingleBannerView, self).dispatch(*args, **kwargs)


class DiscoveryView(TemplateView):
    def get(self, req):
        query_dct = req.GET.dict()
        items, total_count = discovery_db.list_discovery(query_dct)

        resp_items = []
        for item in items:
            item.icon = get_fixed_bucket(item.icon)
            item.updated_at = utc_to_local_str(item.updated_at)
            item.created_at = utc_to_local_str(item.created_at)
            data = item.as_dict()
            if item.abtest:
                data['abtest'] = get_abtest(item.abtest).name
            resp_items.append(data)

        return {'list': resp_items, 'page': query_dct.get('$page', 1),
                'size': len(resp_items), 'total_count': total_count}

    def post(self, req):
        param_dct = json.loads(req.body)
        param_dct['icon'] = get_fixed_bucket(param_dct['icon'],
                                             disable_domain=True)
        discovery_db.upsert_discovery(param_dct)
        return {}

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(DiscoveryView, self).dispatch(*args, **kwargs)


class SingleDiscoveryView(TemplateView):
    def get(self, req, discovery_id):
        discovery = discovery_db.get_discovery(id=int(discovery_id))
        discovery.icon = get_fixed_bucket(discovery.icon)
        discovery.updated_at = utc_to_local_str(discovery.updated_at)
        discovery.created_at = utc_to_local_str(discovery.created_at)
        return discovery.as_dict()

    def put(self, req, discovery_id):
        query_dct = json.loads(smart_unicode(req.body))
        query_dct['icon'] = get_fixed_bucket(query_dct['icon'],
                                             disable_domain=True)
        discovery_db.upsert_discovery(query_dct, int(discovery_id))
        return {}

    def delete(self, req, discovery_id):
        discovery_db.delete_discovery(int(discovery_id))
        return {}

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(SingleDiscoveryView, self).dispatch(*args, **kwargs)


class PayView(TemplateView):
    def get(self, req):
        query_dict = req.GET.dict()
        items, total_count = pay_db.list_pay(query_dict)

        resp_items = []
        for item in items:
            item.icon = get_fixed_bucket(item.icon)
            item.updated_at = utc_to_local_str(item.updated_at)
            item.created_at = utc_to_local_str(item.created_at)
            data = item.as_dict()
            if item.abtest:
                data['abtest'] = get_abtest(item.abtest).name
            resp_items.append(data)

        return {
            'list': resp_items,
            'page': query_dict.get('$page', 1),
            'size': len(resp_items),
            'total_count': total_count
        }

    def post(self, req):
        param_dict = json.loads(req.body)
        param_dict['icon'] = get_fixed_bucket(param_dict['icon'],
                                              disable_domain=True)
        param_dict['highlight'] = bool(param_dict.get('highlight') == '1')
        pay_db.upsert_pay(param_dict)
        return {}

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(PayView, self).dispatch(*args, **kwargs)


class SinglePayView(TemplateView):
    def get(self, req, pay_id):
        pay = pay_db.get_pay(id=int(pay_id))
        pay.icon = get_fixed_bucket(pay.icon)
        pay.updated_at = utc_to_local_str(pay.updated_at)
        pay.created_at = utc_to_local_str(pay.created_at)
        return pay.as_dict()

    def put(self, req, pay_id):
        query_dict = json.loads(smart_unicode(req.body))
        query_dict['icon'] = get_fixed_bucket(query_dict['icon'],
                                              disable_domain=True)
        query_dict['highlight'] = bool(query_dict.get('highlight') == '1')
        pay_db.upsert_pay(query_dict, int(pay_id))
        return {}

    def delete(self, req, pay_id):
        pay_db.delete_pay(int(pay_id))
        return {}

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(SinglePayView, self).dispatch(*args, **kwargs)


class RewardView(TemplateView):
    def get(self, req):
        query_dct = req.GET.dict()
        items, total_count = reward_db.list_reward(query_dct)

        resp_items = []
        for item in items:
            item.updated_at = utc_to_local_str(item.updated_at)
            item.created_at = utc_to_local_str(item.created_at)
            data = item.as_dict()
            resp_items.append(data)

        return {'list': resp_items, 'page': query_dct.get('$page', 1),
                'size': len(resp_items), 'total_count': total_count}

    def post(self, req):
        param_dct = json.loads(req.body)
        reward_db.upsert_reward(param_dct)
        return {}

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(RewardView, self).dispatch(*args, **kwargs)


class SingleRewardView(TemplateView):
    def get(self, req, reward_id):
        reward = reward_db.get_reward(id=int(reward_id))
        reward.updated_at = utc_to_local_str(reward.updated_at)
        reward.created_at = utc_to_local_str(reward.created_at)
        return reward.as_dict()

    def put(self, req, reward_id):
        query_dct = json.loads(smart_unicode(req.body))
        reward_db.upsert_reward(query_dct, int(reward_id))
        return {}

    def delete(self, req, reward_id):
        reward_db.delete_reward(int(reward_id))
        return {}

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(SingleRewardView, self).dispatch(*args, **kwargs)


class RecommendView(TemplateView):
    def get(self, req):
        query_dct = req.GET.dict()
        items, total_count = recommend_db.list_recommend(query_dct)

        resp_items = []
        for item in items:
            item.updated_at = utc_to_local_str(item.updated_at)
            item.created_at = utc_to_local_str(item.created_at)
            data = item.as_dict()
            resp_items.append(data)

        return {'list': resp_items, 'page': query_dct.get('$page', 1),
                'size': len(resp_items), 'total_count': total_count}

    def post(self, req):
        param_dct = json.loads(req.body)
        recommend_db.upsert_recommend(param_dct)
        return {}

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(RecommendView, self).dispatch(*args, **kwargs)


class SingleRecommendView(TemplateView):
    def get(self, req, recommend_id):
        recommend = recommend_db.get_recommend(id=int(recommend_id))
        recommend.updated_at = utc_to_local_str(recommend.updated_at)
        recommend.created_at = utc_to_local_str(recommend.created_at)
        return recommend.as_dict()

    def put(self, req, recommend_id):
        query_dct = json.loads(smart_unicode(req.body))
        recommend_db.upsert_recommend(query_dct, int(recommend_id))
        return {}

    def delete(self, req, reward_id):
        recommend_db.delete_recommend(int(reward_id))
        return {}

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(SingleRecommendView, self).dispatch(*args, **kwargs)


class FloatIconView(TemplateView):
    def get(self, req):
        query_dict = req.GET.dict()
        items, total_count = float_icon_db.list_float_icon(query_dict)

        resp_items = []
        for item in items:
            item.icon = get_fixed_bucket(item.icon)
            item.updated_at = utc_to_local_str(item.updated_at)
            item.created_at = utc_to_local_str(item.created_at)
            item.start_ts = ts_to_local_date_str(item.start_ts)
            item.end_ts = ts_to_local_date_str(item.end_ts)
            data = item.as_dict()
            if item.abtest:
                data['abtest'] = get_abtest(item.abtest).name
            resp_items.append(data)

        return {'list': resp_items, 'page': query_dict.get('$page', 1),
                'size': len(resp_items), 'total_count': total_count}

    def post(self, req):
        param_dict = json.loads(req.body)
        param_dict['icon'] = get_fixed_bucket(param_dict['icon'],
                                              disable_domain=True)
        float_icon_db.upsert_float_icon(param_dict)
        return {}

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(FloatIconView, self).dispatch(*args, **kwargs)


class SingleFloatIconView(TemplateView):
    def get(self, req, float_icon_id):
        float_icon = float_icon_db.get_float_icon(id=int(float_icon_id))
        float_icon.icon = get_fixed_bucket(float_icon.icon)
        float_icon.updated_at = utc_to_local_str(float_icon.updated_at)
        float_icon.created_at = utc_to_local_str(float_icon.created_at)
        float_icon.start_ts = ts_to_local_date_str(float_icon.start_ts)
        float_icon.end_ts = ts_to_local_date_str(float_icon.end_ts)
        return float_icon.as_dict()

    def put(self, req, float_icon_id):
        query_dict = json.loads(smart_unicode(req.body))
        query_dict['icon'] = get_fixed_bucket(query_dict['icon'],
                                              disable_domain=True)
        float_icon_db.upsert_float_icon(query_dict, int(float_icon_id))
        return {}

    def delete(self, req, float_icon_id):
        float_icon_db.delete_float_icon(int(float_icon_id))
        return {}

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(SingleFloatIconView, self).dispatch(*args, **kwargs)


class TabView(TemplateView):
    def get(self, req):
        query_dict = req.GET.dict()
        items, total_count = tab_db.list_tab(query_dict)
        resp_items = []
        for item in items:
            item.updated_at = utc_to_local_str(item.updated_at)
            item.created_at = utc_to_local_str(item.created_at)
            data = item.as_dict()
            resp_items.append(data)

        return {'list': resp_items, 'page': query_dict.get('$page', 1),
                'size': len(resp_items), 'total_count': total_count}

    def post(self, req):
        param_dict = json.loads(req.body)
        tab_db.upsert_tab(param_dict)
        return {}

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(TabView, self).dispatch(*args, **kwargs)


class SingleTabView(TemplateView):
    def get(self, req, tab_id):
        tab = tab_db.get_tab(int(tab_id))
        tab.updated_at = utc_to_local_str(tab.updated_at)
        tab.created_at = utc_to_local_str(tab.created_at)
        return tab.as_dict()

    def put(self, req, tab_id):
        query_dict = json.loads(smart_unicode(req.body))
        tab_db.upsert_tab(query_dict, int(tab_id))
        return {}

    def delete(self, req, tab_id):
        tab_db.delete_tab(int(tab_id))
        return {}

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(SingleTabView, self).dispatch(*args, **kwargs)


class LotteryView(TemplateView):
    def get(self, req):
        query_dict = req.GET.dict()
        items, total_count = lottery_db.list_lottery(query_dict)
        resp_items = []
        for item in items:
            item.image = get_fixed_bucket(item.image)
            item.updated_at = utc_to_local_str(item.updated_at)
            item.created_at = utc_to_local_str(item.created_at)
            item.start_ts = ts_to_local_date_str(item.start_ts)
            item.end_ts = ts_to_local_date_str(item.end_ts)
            data = item.as_dict()
            resp_items.append(data)

        return {'list': resp_items, 'page': query_dict.get('$page', 1),
                'size': len(resp_items), 'total_count': total_count}

    def post(self, req):
        param_dict = json.loads(req.body)
        param_dict['image'] = get_fixed_bucket(param_dict['image'],
                                               disable_domain=True)
        lottery_db.upsert_lottery(param_dict)
        return {}

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(LotteryView, self).dispatch(*args, **kwargs)


class SingleLotteryView(TemplateView):
    def get(self, req, lottery_id):
        lottery = lottery_db.get_lottery(int(lottery_id))
        lottery.image = get_fixed_bucket(lottery.image)
        lottery.updated_at = utc_to_local_str(lottery.updated_at)
        lottery.created_at = utc_to_local_str(lottery.created_at)
        lottery.start_ts = ts_to_local_date_str(lottery.start_ts)
        lottery.end_ts = ts_to_local_date_str(lottery.end_ts)
        off_status = redis_cache.get_activity_switch(lottery.type)
        data = lottery.as_dict()
        data['off_status'] = off_status
        return data

    def put(self, req, lottery_id):
        query_dict = json.loads(smart_unicode(req.body))
        query_dict['image'] = get_fixed_bucket(query_dict['image'],
                                               disable_domain=True)
        query_dict['exclude_chn'] = clean_chn(query_dict['exclude_chn'])
        lottery_db.upsert_lottery(query_dict, int(lottery_id))
        return {}

    def delete(self, req, lottery_id):
        lottery_db.delete_lottery(int(lottery_id))
        return {}

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(SingleLotteryView, self).dispatch(*args, **kwargs)


def _wrap_profit_rates(profit_rate):
    profit_rate_dict = profit_rate.as_dict()
    system_win, total_bet = get_daily_pool_info(profit_rate_dict['activity_type'])

    profit_rate_dict['current_profit_rate'] = system_win / float(total_bet) if total_bet else 0
    profit_rate_dict['current_total_bet'] = float(total_bet)
    return profit_rate_dict


class ProfitRateView(TemplateView):
    def get(self, req):
        profit_rates = profit_rate_db.get_profit_rate_list()

        return [_wrap_profit_rates(profit_rate) for profit_rate in profit_rates]

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(ProfitRateView, self).dispatch(*args, **kwargs)


class SingleProfitRateView(TemplateView):
    def put(self, req, profit_rate_id):
        query_dict = json.loads(smart_unicode(req.body))
        profit_rate_db.update_profit_rate(preset_id=profit_rate_id, **query_dict)
        return {}

    def delete(self, req, lottery_id):
        lottery_db.delete_lottery(int(lottery_id))
        return {}

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(SingleProfitRateView, self).dispatch(*args, **kwargs)


@require_POST
@response_wrapper
@token_required
def set_chn_links(req, platform):
    chn_links = json.loads(req.body)
    redis_cache.set_chn_links(platform, chn_links)
    return {}


@require_GET
@response_wrapper
@token_required
def get_chn_links(req, platform):
    l = []
    chn_links = redis_cache.get_chn_links(platform)
    for chn, link in chn_links.items():
        l.append({
            'chn': chn,
            'link': link
        })
    return {'list': l, 'page': 1, 'size': len(l),
            'stock': [], 'total_count': len(l)}


@require_POST
@response_wrapper
@token_required
def switch_lottery(req, lottery_type, off):
    redis_cache.set_activity_switch(lottery_type, off)
    return {}
